import pickle
from .getModelFromGeneral import getModelFromGeneral
from .utils import GeneralTools
from .config import pickle_file_path
from django.conf import settings
from . import config
import os


def wet_to_dry(wet, materials_chemical_dict):
    '''湿基转干基'''
    dry = {}
    for k, wet_item in wet.items():
        dry[k] = wet_item * (1 - materials_chemical_dict[k]["水份"])
    dry = GeneralTools.normalize(dry)
    return dry

def calc_balance_dry_from_feedback_dry(feedback_dry, process_quality_dict, materials_chemical_dict):
    # LOGGER.info(f"feedback_dry = {feedback_dry}")
    '''
    根据反馈值计算平衡干基。

    Args:
        feedback_dry (dict): 反馈干基字典。
        process_quality_dict (dict): 过程质量字典，包含不同参数的质量值。
        materials_chemical_dict (dict): 物料化学成分字典，包含不同化学成分的值。

    Returns:
        float: 计算得到的平衡干基值。

    Notes:
        这个函数根据传入的反馈干基字典、过程质量字典和物料化学成分字典，
        计算出平衡干基字典并返回。
        具体计算公式和参数的作用请参考相关文档。
    '''

    # 1.抽象石膏
    abs_gyp_flag = True if "石膏" in feedback_dry.keys() else False

    # 2. 具体石膏处理
    con_gyp_flag = False
    con_gyp_list = []
    gyp_thre = config.gyp_thre/100
    for i in materials_chemical_dict.keys():
        if materials_chemical_dict[i]["SO3"] > gyp_thre and i in feedback_dry.keys():
            con_gyp_flag = True
            con_gyp_list.append(i)
    if not abs_gyp_flag and not con_gyp_flag:
        msg = "抽象石膏 具体石膏都不存在"
        raise ValueError(msg)



    def calculate_process_index(material, feedback, process_index):

        a =materials_chemical_dict[material][process_index]
        b = feedback[material]
        product = a * b
        return product

    admixture_list = list(set(feedback_dry.keys()) - {'熟料', '石灰石', "石膏"})
    # 1. SO3 --> 石膏
    if abs_gyp_flag:
        clinker_SO3 = materials_chemical_dict['熟料']['SO3'] * feedback_dry['熟料']
        limestone_SO3 = materials_chemical_dict['石灰石']['SO3'] * feedback_dry['石灰石']
        admixture_SO3 = sum(calculate_process_index(admixture, feedback_dry,"SO3") for admixture in admixture_list)
        gypsum_SO3 = process_quality_dict['SO3'] - clinker_SO3 - limestone_SO3 - admixture_SO3
        gypsum_balance_dry = gypsum_SO3 / materials_chemical_dict['石膏']['SO3']
    else:
        gypsum_balance_dry =0

    # 2. Loss --> 石灰石
    if '石灰石掺量' in process_quality_dict.keys():
        limestone_balance_dry = process_quality_dict['石灰石掺量']
    else:
        clinker_Loss = materials_chemical_dict['熟料']['Loss'] * feedback_dry['熟料']
        if abs_gyp_flag:
            gypsum_Loss = gypsum_balance_dry * materials_chemical_dict['石膏']['Loss']
        else:
            gypsum_Loss = 0
        admixture_Loss = sum(calculate_process_index(admixture, feedback_dry, "Loss") for admixture in admixture_list)
        limestone_Loss = process_quality_dict['Loss'] - clinker_Loss - gypsum_Loss - admixture_Loss
        # limestone_balance_dry = limestone_Loss / materials_chemical_dict['石灰石']['Loss']
        # modified 2024.9.25
        if feedback_dry['石灰石'] == 0:
            limestone_balance_dry = 0
        else:
            limestone_balance_dry = limestone_Loss / materials_chemical_dict['石灰石']['Loss']

    # 3. CaO --> 熟料
    if '混合材总掺量' in process_quality_dict.keys():
        clinker_balance_dry = 100 - process_quality_dict['混合材总掺量'] - gypsum_balance_dry
    else:
        if abs_gyp_flag:
            gypsum_Cao = gypsum_balance_dry * materials_chemical_dict['石膏']['CaO']
        else:
            gypsum_Cao = 0
        limestone_Cao = limestone_balance_dry * materials_chemical_dict['石灰石']['CaO']
        admixture_CaO = sum(calculate_process_index(admixture, feedback_dry, "CaO") for admixture in admixture_list)
        clinker_Cao = process_quality_dict['CaO'] - gypsum_Cao - limestone_Cao - admixture_CaO
        clinker_balance_dry = clinker_Cao / materials_chemical_dict['熟料']['CaO']

    # 混合材（水渣/ 建筑垃圾） 入磨物料平衡干基
    if '混合材总掺量' in process_quality_dict.keys():
        remain_balance_dry = process_quality_dict['混合材总掺量'] - limestone_balance_dry
    else:
        remain_balance_dry = 100 - (gypsum_balance_dry + limestone_balance_dry + clinker_balance_dry)
    feedback_dry_admixture_sum = sum(feedback_dry[admixture] for admixture in admixture_list)
    if (remain_balance_dry > 0)&(feedback_dry_admixture_sum>0):
        balance_dry = {admixture: feedback_dry[admixture] / feedback_dry_admixture_sum * remain_balance_dry for
                       admixture in admixture_list}
        if abs_gyp_flag:
            balance_dry.update({'熟料': clinker_balance_dry, '石灰石': limestone_balance_dry, '石膏': gypsum_balance_dry})
        else:
            balance_dry.update(
                {'熟料': clinker_balance_dry, '石灰石': limestone_balance_dry})
    else:
        if abs_gyp_flag:
            base_dict = {'熟料': clinker_balance_dry, '石灰石': limestone_balance_dry, '石膏': gypsum_balance_dry}
        else:
            base_dict = {'熟料': clinker_balance_dry, '石灰石': limestone_balance_dry}
        admixture_dict = {admixture: feedback_dry[admixture] for admixture in admixture_list}
        base_dict.update(admixture_dict)
        balance_dry = GeneralTools.normalize(base_dict)
    return balance_dry

def integrate_gypsum_into_chemical(chemical_dict, gyp_ratio):

    '''整合石膏化学成份'''

    # # 通用版
    chemical_dict['石膏'] = {}
    gyp_type = list(gyp_ratio.keys())
    denominator = sum(gyp_ratio.values())
    for chemical_analysis in chemical_dict[gyp_type[0]]:
        chemical_dict["石膏"][chemical_analysis] = sum(chemical_dict[k][chemical_analysis]*v for k,v in gyp_ratio.items())/denominator
    for i in gyp_type:
        if "石膏" in i and len(i) > len("石膏"):
            chemical_dict.pop(i)

def transform_ci_to_nl(dictionary, name_dict):
    """主数据格式转换"""
    result_dict = {}
    for key, value in dictionary.items():
        new_key = name_dict.get(key, key) if isinstance(key, str) and key.startswith("CI") else key
        new_value = name_dict.get(value, value) if isinstance(value, str) and value.startswith("CI") else value

        if isinstance(new_value, dict):
            # 递归调用以处理嵌套的字典
            result_dict[new_key] = transform_ci_to_nl(new_value, name_dict)
        elif isinstance(new_value, list):
            result_dict[new_key] = [name_dict[item] for item in new_value]
        else:
            result_dict[new_key] = new_value
    return result_dict

def transform_nl_to_ci(dictionary, reverse_name_dict):
    """主数据格式转换"""
    result_dict = {}
    for key, value in dictionary.items():
        # new_key = reverse_name_dict.get(key, key) if isinstance(key, str) else key
        new_key = reverse_name_dict.get(key, key)
        new_value = reverse_name_dict.get(value, value) if isinstance(value, str) else value

        if isinstance(new_value, dict):
            # 递归调用以处理嵌套的字典
            result_dict[new_key] = transform_nl_to_ci(new_value, reverse_name_dict)
        elif isinstance(new_value, list):
            result_dict[new_key] = [reverse_name_dict[item] for item in new_value]
        else:
            result_dict[new_key] = new_value
    return result_dict

def convert_str_to_float(dictionary):
    """
    将字典中的所有嵌套值转换为float
    """
    result_dict = {}
    for key, value in dictionary.items():
        if isinstance(value, dict):
            # 递归调用以处理嵌套字典
            result_dict[key] = convert_str_to_float(value)
        elif isinstance(value, str) and value.replace('.', '', 1).lstrip('-').isdigit():
            # 如果值是字符串且能被转换为float，则转换
            result_dict[key] = float(value)
        else:
            # 其他情况保持原样
            result_dict[key] = value

    return result_dict

def get_coef_from_pickle(model_type, model_code):
    
    full_path = os.path.join(pickle_file_path, model_code + '_{}.pkl'.format(settings.linear_suffix[int(model_type)]))
    with open(full_path, "rb") as pickle_file:
        model_coef = pickle.load(pickle_file)
    params_3d = model_coef["3d"]
    params_28d = model_coef["28d"]
    try:
        params_3d['截距']=params_3d['intercept']
        params_28d['截距']=params_28d['intercept']
    except:
        pass
    return params_3d,params_28d

def get_coef(model_type, model_code, app_set, chemical_dict,abs_gyp_flag,con_gyp_flag,con_gyp_list):
    # coef_3d_local, coef_28d_local = get_coef_from_pickle(get_model_name(model_type, model_code))
    coef_3d_local, coef_28d_local = get_coef_from_pickle(model_type, model_code)
    coef_3d_local['熟料'],coef_28d_local['熟料'] = 0,0
    cement_list = []
    if abs_gyp_flag:
        coef_3d_local['石膏'],coef_28d_local['石膏'] = 0,0
    if con_gyp_flag:
        app_set= app_set-set(con_gyp_list)
    if model_type != 1:
        local_set = set(coef_3d_local.keys()) - {"比表", "细度45μm", "SO3", "截距"}
    else:
        local_set = set(coef_3d_local.keys()) - {"比表", "细度45μm", "SO3", "截距","1d"}

    tmp_app_set = app_set | {"SO3", "比表", "细度45μm"}
    if local_set == app_set:                # 应用 == 本地
        print("local_set == app_set")
        coef_3d = {i: coef_3d_local[i] for i in tmp_app_set}
        coef_28d = {i: coef_28d_local[i] for i in tmp_app_set}
        intercept_3d, intercept_28d = coef_3d_local["截距"], coef_28d_local["截距"]
        if model_type == 1:
            cement_3d_1d, cement_28d_1d = coef_3d_local["1d"], coef_28d_local["1d"]
            cement_list.append(cement_3d_1d)
            cement_list.append(cement_28d_1d)
        if model_type == 2:
            cement_28d_3d = coef_28d_local["3d"]
            cement_list.append(cement_28d_3d)

    elif local_set < app_set:               # 本地 < 应用
        print("local_set < app_set")
        coef_3d_gen,coef_28d_gen = getModelFromGeneral(chemical_dict)
        coef_3d_gen['熟料'], coef_28d_gen['熟料'], coef_3d_gen['石膏'], coef_28d_gen['石膏'] = 0, 0, 0, 0
        coef_3d = {i: coef_3d_gen[i] for i in tmp_app_set}
        coef_28d = {i: coef_28d_gen[i] for i in tmp_app_set}
        intercept_3d, intercept_28d = coef_3d_local["截距"], coef_28d_local["截距"]
        if model_type == 1:
            cement_3d_1d, cement_28d_1d = coef_3d_local["1d"], coef_28d_local["1d"]
            cement_list.append(cement_3d_1d)
            cement_list.append(cement_28d_1d)
        if model_type == 2:
            cement_28d_3d = coef_28d_local["3d"]
            cement_list.append(cement_28d_3d)

    elif local_set > app_set:               # 本地 > 应用
        print("local_set > app_set")
        coef_3d = {i: coef_3d_local[i] for i in tmp_app_set}
        coef_28d = {i: coef_28d_local[i] for i in tmp_app_set}
        intercept_3d, intercept_28d = coef_3d_local["截距"], coef_28d_local["截距"]
        if model_type == 1:
            cement_3d_1d, cement_28d_1d = coef_3d_local["1d"], coef_28d_local["1d"]
            cement_list.append(cement_3d_1d)
            cement_list.append(cement_28d_1d)
        if model_type == 2:
            cement_28d_3d = coef_28d_local["3d"]
            cement_list.append(cement_28d_3d)

    else:                                   # 不相等也不包含
        print("local_set  app_set不相等也不包含")
        coef_3d_gen, coef_28d_gen = getModelFromGeneral(chemical_dict)
        coef_3d_gen['熟料'], coef_28d_gen['熟料'], coef_3d_gen['石膏'], coef_28d_gen['石膏'] = 0, 0, 0, 0
        coef_3d = {i: coef_3d_gen[i] for i in tmp_app_set}
        coef_28d = {i: coef_28d_gen[i] for i in tmp_app_set}
        intercept_3d, intercept_28d = coef_3d_local["截距"], coef_28d_local["截距"]
        if model_type == 1:
            cement_3d_1d, cement_28d_1d = coef_3d_local["1d"], coef_28d_local["1d"]
            cement_list.append(cement_3d_1d)
            cement_list.append(cement_28d_1d)
        if model_type == 2:
            cement_28d_3d = coef_28d_local["3d"]
            cement_list.append(cement_28d_3d)

    # coef_3d['熟料'], coef_28d['熟料'], coef_3d['石膏'], coef_28d['石膏'] = 0, 0, 0, 0
    if con_gyp_flag:
        for gyp in con_gyp_list:
            coef_3d[gyp],coef_28d[gyp] = 0,0
    return coef_3d,coef_28d,intercept_3d, intercept_28d, cement_list

